"""
    This class supplies the IO routines to read/write config files
"""

from NodeHandler import MapDirective
from Cruft import Cruft

import pdb

def _get_tab_level(level):
    """
    Utility function to support neat file output
    """
    tab = ""
    for i in range(0, level):
        tab += "\t"
    return tab

class ConfigIO:
    def write_config(self, path, node):
        """
        Dump the given tree to a file...
        """
        fin = open(path, "w")
        
        def _write_config(f, node, level=0):
            """Write out the config file..."""
            for n in node.children:
                #Obviously we don't write deleted nodes
                if not n.is_deleted:
                    if n.directive == "Include":
                        #Special handling for includes - write out the directives under an include node to the specified
                        #file

                        #The 'real' file includes are always children of the first include. The parent include contains the 
                        #directive to output. 
                        tab = _get_tab_level(level)
                        f.write( ''.join([tab, str(n), "\n" ]))
                        print( ''.join([tab, str(n), "\n" ]) ),
                        
                        #write out the include file info... 
                        for child in n.children:
                            if child.directive != 'Cruft' :
                                self.write_config(' '.join(child.args), child)
                    else:
                        tab = _get_tab_level(level)
                        f.write( ''.join([tab, str(n), "\n" ]) )
                        print( ''.join([tab, str(n), "\n" ]) ),
                        _write_config(f, n, level + 1)
            #write the end tag
            if node.is_scoped:
                tab = _get_tab_level(level - 1)
                f.write(tab + "</" + node.directive + ">\n")
                print(tab + "</" + node.directive + ">\n"),
            
        _write_config(fin, node)
        fin.close()
        
    def read_config(self, node):
        """
        Return a read_config closure
        """
        def _read_config(path):
            """
            Read in an apache config file and return the root node to
            the corresponding tree
            """
            level = []
            root = node 
            current = root
            current_comment = ""
            f = open( path, 'r' )
            
            #XXX Must still deal with escaped lines...
            
            line_no = 0
            
            for line in f:
                line_no += 1
                if( (line.lstrip().find("#") != 0) and (line.strip() != "") ):
                    parse = line.rstrip('> \n').split()
                    directive = parse[0]
                    args = parse[1:]

                    #Don't add end tags...
                    if not directive.startswith( "</" ):
                        m = MapDirective(directive.lstrip('< '), args)
                        m.parent = current

                        #XXX The fact that we need to explicitly call this is cruddy... Remind me to fix it
                        try:
                            m.validate()
                        except Exception, e:
                            print "Error on line " + str(line_no) + " : " + str(e)

                        if current_comment != "":
                            cruft = Cruft(current_comment)
                            current.append_node(cruft)
                            current_comment = ""
                        m.file = path
                        current.append_node(m)

                        if( m.directive == "Include" ):
                            m.do_include()

                    #check for scoped directive
                    if( directive.find( r"<" ) != -1 ):
                        #go up a level
                        if( directive.startswith( r"</" ) ):
                            current = level.pop()
                        else: #go down a level
                            level.append( current )
                            current = m
                else:
                    current_comment += line

            #Cater for comments and newlines after the last directive
            if current_comment != "":
                cruft = Cruft(current_comment)
                root.append_node(cruft)

            f.close()
            return root
        return _read_config



